const express = require('express');
const multer = require('multer');
const cors = require('cors');
const path = require('path');
const fs = require('fs');
const { spawn } = require('child_process');

const app = express();
const port = 5000;

// Blender路径配置
const BLENDER_PATH = 'E:\\Program Files\\Blender Foundation\\Blender4.4\\blender.exe';

// 中间件
app.use(cors());
app.use(express.json());

// 创建必要目录
const ensureDirectoryExists = (dirPath) => {
  if (!fs.existsSync(dirPath)) {
    fs.mkdirSync(dirPath, { recursive: true });
    console.log(`创建目录: ${dirPath}`);
  }
};

ensureDirectoryExists('uploads');
ensureDirectoryExists('output');

// 文件上传配置
const storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, 'uploads/');
  },
  filename: (req, file, cb) => {
    cb(null, Date.now() + '-' + file.originalname);
  }
});

const upload = multer({ 
  storage: storage,
  limits: {
    fileSize: 100 * 1024 * 1024 // 100MB
  },
  fileFilter: (req, file, cb) => {
    if (file.fieldname === 'image') {
      if (file.mimetype.startsWith('image/')) {
        cb(null, true);
      } else {
        cb(new Error('只允许上传图片文件'));
      }
    } else if (file.fieldname === 'model') {
      const allowedExts = ['.obj', '.glb', '.gltf'];
      const ext = path.extname(file.originalname).toLowerCase();
      if (allowedExts.includes(ext)) {
        cb(null, true);
      } else {
        cb(new Error('只允许上传OBJ, GLB, GLTF格式的模型文件'));
      }
    } else {
      cb(new Error('未知的文件字段'));
    }
  }
});

// 清理文件函数
const cleanupFile = (filePath) => {
  if (fs.existsSync(filePath)) {
    try {
      fs.unlinkSync(filePath);
      console.log(`已删除临时文件: ${filePath}`);
    } catch (error) {
      console.error(`删除文件失败: ${filePath}`, error);
    }
  }
};

// 验证Blender路径
const verifyBlenderPath = () => {
  if (!fs.existsSync(BLENDER_PATH)) {
    console.error(`Blender文件不存在: ${BLENDER_PATH}`);
    return false;
  }
  console.log(`Blender路径验证成功: ${BLENDER_PATH}`);
  return true;
};

// 健康检查路由
app.get('/api/health', (req, res) => {
  const blenderExists = fs.existsSync(BLENDER_PATH);
  res.json({
    status: 'OK',
    timestamp: new Date().toISOString(),
    message: '3D模型贴图服务器运行正常',
    blenderPath: BLENDER_PATH,
    blenderAvailable: blenderExists,
    endpoints: [
      '/api/health',
      '/api/apply-texture'
    ]
  });
});

// 基础路由
app.get('/', (req, res) => {
  res.json({ 
    message: '3D模型贴图服务器运行正常',
    timestamp: new Date().toISOString()
  });
});

// 获取模型材质信息路由
app.post('/api/get-materials', upload.single('model'), async (req, res) => {
  let tempFiles = [];
  
  try {
    if (!req.file) {
      return res.status(400).json({ error: '缺少模型文件' });
    }

    const modelFile = req.file;
    tempFiles.push(modelFile.path);
    
    console.log(`获取材质信息: ${modelFile.originalname}`);

    // 生成临时输出文件路径
    const outputPath = path.join('output', `materials_${Date.now()}.json`);
    tempFiles.push(outputPath);

    // 调用Blender获取材质信息（使用现有脚本的材质获取模式）
    const blenderProcess = spawn(BLENDER_PATH, [
      '--background',
      '--python', 'Texture_Painting_Interface.py',
      '--',
      '--obj_path', path.resolve(modelFile.path),
      '--output_path', path.resolve(outputPath),
      '--get_materials', 'true'  // 添加材质获取标志
    ]);

    let stdout = '';
    let stderr = '';

    blenderProcess.stdout.on('data', (data) => {
      stdout += data.toString();
    });

    blenderProcess.stderr.on('data', (data) => {
      stderr += data.toString();
    });

    blenderProcess.on('close', (code) => {
      if (code === 0 && fs.existsSync(outputPath)) {
        try {
          const materialsData = JSON.parse(fs.readFileSync(outputPath, 'utf8'));
          console.log('获取材质成功:', materialsData);
          
          res.json({ 
            success: true,
            materials: materialsData
          });
          
        } catch (error) {
          console.error('解析材质信息失败:', error);
          res.status(500).json({ error: '解析材质信息失败' });
        }
      } else {
        console.error(`获取材质失败, 退出代码: ${code}`);
        res.status(500).json({ 
          error: '获取材质信息失败',
          details: stderr || `进程退出代码: ${code}`
        });
      }
      
      // 清理临时文件
      tempFiles.forEach(cleanupFile);
    });

    blenderProcess.on('error', (error) => {
      console.error('启动Blender进程失败:', error);
      res.status(500).json({ 
        error: '启动Blender失败',
        details: error.message 
      });
      tempFiles.forEach(cleanupFile);
    });

  } catch (error) {
    console.error('处理请求失败:', error);
    tempFiles.forEach(cleanupFile);
    
    if (!res.headersSent) {
      res.status(500).json({ 
        error: '服务器内部错误',
        details: error.message 
      });
    }
  }
});

// 主要的贴图处理路由
app.post('/api/apply-texture', upload.fields([
  { name: 'image', maxCount: 1 },
  { name: 'model', maxCount: 1 }
]), async (req, res) => {
  let tempFiles = [];
  
  try {
    console.log('=== 开始处理贴图请求 ===');
    
    // 验证上传文件
    if (!req.files || !req.files['image'] || !req.files['model']) {
      return res.status(400).json({ error: '缺少图片或模型文件' });
    }

    const imageFile = req.files['image'][0];
    const modelFile = req.files['model'][0];
    
    tempFiles.push(imageFile.path, modelFile.path);
    
    console.log(`接收到文件:`);
    console.log(`图片: ${imageFile.originalname} (${imageFile.size} bytes)`);
    console.log(`模型: ${modelFile.originalname} (${modelFile.size} bytes)`);

    // 验证Blender路径
    if (!fs.existsSync(BLENDER_PATH)) {
      throw new Error(`Blender文件不存在: ${BLENDER_PATH}`);
    }

    // 验证Python脚本
    if (!fs.existsSync('Texture_Painting_Interface.py')) {
      throw new Error('Python脚本文件不存在: Texture_Painting_Interface.py');
    }

    // 生成输出文件路径
    const timestamp = Date.now();
    const originalName = path.parse(modelFile.originalname).name; // 获取原始文件名（不包含扩展名）
    const outputFilename = `${originalName}_textured_${timestamp}.glb`; 
    const outputPath = path.join('output', outputFilename);
    
    tempFiles.push(outputPath);

    console.log(`输出文件路径: ${outputPath}`);
    console.log(`开始调用Blender处理...`);

    // 调用Blender处理
    const blenderProcess = spawn(BLENDER_PATH, [
      '--background',
      '--python', 'Texture_Painting_Interface.py',
      '--',
      '--obj_path', path.resolve(modelFile.path),
      '--output_path', path.resolve(outputPath),
      '--texture_path', path.resolve(imageFile.path),
      '--material_name', req.body.materialName || 'ProjectionArea'  // 材质名称参数
    ]);

    let stdout = '';
    let stderr = '';

    // 收集输出
    blenderProcess.stdout.on('data', (data) => {
      const output = data.toString();
      stdout += output;
      console.log(`[Blender] ${output.trim()}`);
    });

    blenderProcess.stderr.on('data', (data) => {
      const output = data.toString();
      stderr += output;
      console.error(`[Blender Error] ${output.trim()}`);
    });

    // 处理完成
    blenderProcess.on('close', (code) => {
      console.log(`Blender进程退出，代码: ${code}`);
      
      if (code === 0) {
        // 检查输出文件是否存在
        if (fs.existsSync(outputPath)) {
          const stats = fs.statSync(outputPath);
          console.log(`处理成功，输出文件大小: ${stats.size} bytes`);
          
          // 设置响应头
          res.setHeader('Content-Type', 'model/gltf-binary');
          res.setHeader('Content-Disposition', `attachment; filename="${outputFilename}"`);
          
          // 发送文件
          res.sendFile(path.resolve(outputPath), (err) => {
            if (err) {
              console.error('发送文件失败:', err);
              if (!res.headersSent) {
                res.status(500).json({ error: '文件发送失败' });
              }
            } else {
              console.log('文件发送成功');
            }
            
            // 清理临时文件
            setTimeout(() => {
              cleanupFile(imageFile.path);
              cleanupFile(modelFile.path);
              // 注意：不删除输出文件，可能还需要用于其他请求
            }, 1000);
          });
        } else {
          console.error('Blender处理完成但未生成输出文件');
          res.status(500).json({ error: 'Blender处理完成但未生成输出文件' });
          tempFiles.forEach(cleanupFile);
        }
      } else {
        console.error(`Blender处理失败,退出代码: ${code}`);
        console.error(`错误输出: ${stderr}`);
        res.status(500).json({ 
          error: 'Blender处理失败',
          details: stderr || `进程退出代码: ${code}`
        });
        tempFiles.forEach(cleanupFile);
      }
    });

    // 处理错误
    blenderProcess.on('error', (error) => {
      console.error('启动Blender进程失败:', error);
      res.status(500).json({ 
        error: '启动Blender失败',
        details: error.message 
      });
      tempFiles.forEach(cleanupFile);
    });

  } catch (error) {
    console.error('处理请求失败:', error);
    tempFiles.forEach(cleanupFile);
    
    if (!res.headersSent) {
      res.status(500).json({ 
        error: '服务器内部错误',
        details: error.message 
      });
    }
  }
});

// 错误处理中间件
app.use((error, req, res, next) => {
  console.error('服务器错误:', error);
  
  if (error instanceof multer.MulterError) {
    if (error.code === 'LIMIT_FILE_SIZE') {
      return res.status(400).json({ error: '文件大小超过限制(100MB)' });
    }
    return res.status(400).json({ error: `文件上传错误: ${error.message}` });
  }
  
  if (!res.headersSent) {
    res.status(500).json({ 
      error: '服务器内部错误',
      details: error.message
    });
  }
});

// 启动服务器
app.listen(port, () => {
  console.log(`========================================`);
  console.log(`  3D模型贴图服务器已启动`);
  console.log(`========================================`);
  console.log(`服务器地址: http://localhost:${port}`);
  console.log(`健康检查: http://localhost:${port}/api/health`);
  console.log(`Blender路径: ${BLENDER_PATH}`);
  
  // 验证Blender路径
  const blenderValid = verifyBlenderPath();
  if (!blenderValid) {
    console.log(`警告: Blender路径无效,贴图功能将无法工作`);
  }
  
  // 验证Python脚本
  if (fs.existsSync('Texture_Painting_Interface.py')) {
    console.log(`Python脚本: Texture_Painting_Interface.py`);
  } else {
    console.log(`警告: Python脚本不存在`);
  }
  
  console.log(`========================================`);
});